package group.rober.jeki.controller;

import group.rober.common.entity.FileEntity;
import group.rober.common.service.FileManageService;
import group.rober.jeki.entity.Article;
import group.rober.jeki.entity.Comment;
import group.rober.jeki.service.ArticleService;
import group.rober.jeki.service.CommentService;
import group.rober.jeki.service.DomainService;
import group.rober.jeki.service.TagService;
import group.rober.saber.holder.WebHolder;
import group.rober.saber.kit.*;
import group.rober.saber.lang.RoberException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Controller
@RequestMapping("/article")
public class ArticleController {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    static private Map<String,String> contentTypeMap = new HashMap<String,String>();
    static{
        contentTypeMap.put("application/vnd.ms-powerpoint","ppt");
        contentTypeMap.put("application/vnd.openxmlformats-officedocument.presentationml.presentation","pptx");
        contentTypeMap.put("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","xlsx");
        contentTypeMap.put("application/vnd.ms-excel","xls");
        contentTypeMap.put("application/msword","doc");
        contentTypeMap.put("application/vnd.openxmlformats-officedocument.wordprocessingml.document","docx");
    }

    @Autowired
    ArticleService articleService;
    @Autowired
    CommentService commentService;
    @Autowired
    TagService tagService;
    @Autowired
    DomainService domainService;

    @Autowired
    @Qualifier("imageFileService")
    FileManageService imageFileService;

    @Autowired
    @Qualifier("docFileService")
    FileManageService docFileService;

    @RequestMapping("/{articleId}.html")
    public ModelAndView article(@PathVariable("articleId") String articleId) {
        //取出文章对象
        Article article = articleService.getArticle(articleId);

        //文章的PV数加1
        articleService.incrementViewCount(articleId);
        Map<String,Object> vars = MapKit.newHashMap();
        fillArticleModel(article,vars);
        vars.put("commentList",commentService.getCommentListByArticle(articleId));

        ModelAndView modelAndView = null;
        if("markdown".equals(article.getFormat())){
            modelAndView = new ModelAndView("views/article-markdown",vars);
        }else if("richtext".equals(article.getFormat())){
            modelAndView = new ModelAndView("views/article-richtext",vars);
        }else if("pdf".equals(article.getFormat())){
            modelAndView = new ModelAndView("views/article-pdf",vars);
        }

        return modelAndView;
    }

    @RequestMapping("/create/{textFormat}")
    public ModelAndView createArticle(@PathVariable("textFormat") String textFormat) {
        Map<String,Object> vars = MapKit.newHashMap();
        Article article = new Article();
        article.setTitle("");
        fillArticleModel(article,vars);
        ModelAndView modelAndView = null;
        article.setFormat(textFormat);
        if("markdown".equals(textFormat)){
            modelAndView = new ModelAndView("views/article-editor-markdown",vars);
        }else if("richtext".equals(textFormat)){
            modelAndView = new ModelAndView("views/article-editor-richtext",vars);
        }else if("pdf".equals(textFormat)){
            modelAndView = new ModelAndView("views/article-editor-pdf",vars);
        }
        return modelAndView;
    }
    @RequestMapping(path="/save-action",method = RequestMethod.POST)
    public ModelAndView createArticleAction(@ModelAttribute Article article) {
        Article persisArticle = article;
        //如果没有ID，则给一个默认的
        if(StringKit.isBlank(article.getId())){
            article.setId(NumberKit.nanoTime36());
        }else{
            persisArticle= articleService.getArticle(article.getId());
        }
        //重新设置下内容及标签
        persisArticle.setTitle(article.getTitle());
        persisArticle.setSummary(article.getSummary());
        persisArticle.setContent(article.getContent());
        persisArticle.setTags(article.getTags());

        articleService.saveArticle(persisArticle);
        return new ModelAndView("redirect:/article/"+article.getId()+".html");
    }
    @RequestMapping(path="/delete-action")
    public ModelAndView deleteArticleAction() {
        return new ModelAndView("redirect:/article/");
    }

    @RequestMapping("/editor/{articleId}")
    public ModelAndView editArticle(@PathVariable("articleId") String articleId) {
        Article article = articleService.getArticle(articleId);

        Map<String,Object> vars = MapKit.newHashMap();
        fillArticleModel(article,vars);

        ModelAndView modelAndView = null;
        if("markdown".equals(article.getFormat())){
            modelAndView = new ModelAndView("views/article-editor-markdown",vars);
        }else if("richtext".equals(article.getFormat())){
            modelAndView = new ModelAndView("views/article-editor-richtext",vars);
        }else if("pdf".equals(article.getFormat())){
            modelAndView = new ModelAndView("views/article-editor-pdf",vars);
        }
        return modelAndView;
    }
    @RequestMapping(path="/add-comment/{articleId}",method = RequestMethod.POST)
    public ModelAndView addComment(@PathVariable("articleId") String articleId,@ModelAttribute Comment comment) {
        comment.setId(NumberKit.nanoTime36());
        comment.setArticleId(articleId);
        comment.setType("ArticleComment");
        commentService.addComment(comment);

        return new ModelAndView("redirect:/article/"+articleId+".html");
    }
    @RequestMapping(path="/delete-comment/{articleId}/{commentId}",method = RequestMethod.GET)
    public ModelAndView deleteComment(@PathVariable("articleId") String articleId,@PathVariable("commentId") String commentId) {
        commentService.deleteComment(commentId);

        return new ModelAndView("redirect:/article/"+articleId+".html");
    }

    protected FileEntity saveFileAsSingle(MultipartHttpServletRequest multiRequest,FileManageService fileManage) throws IOException {
        // 获取上传文件的路径
        Iterator<String> iterator = multiRequest.getFileNames();
        String fileId = "";
        FileEntity fe = null;
        if(iterator.hasNext()){
            String name = iterator.next();
            MultipartFile mpFile = multiRequest.getFile(name);

            String originalFilename = mpFile.getOriginalFilename();
            File file = new File(originalFilename);

            originalFilename = originalFilename.replaceAll("\\\\","/");// 截取上传文件的文件名

            String uploadFileName = originalFilename.substring(originalFilename.lastIndexOf('/') + 1, originalFilename.lastIndexOf('.'));
            String uploadFileSuffix = originalFilename.substring(originalFilename.lastIndexOf('.') + 1, originalFilename.length());// 截取上传文件的后缀

            System.out.println("文件路径:" + originalFilename);
            System.out.println("文件名:" + uploadFileName);
            System.out.println("扩展名:" + uploadFileSuffix);

            fileId = NumberKit.nanoTime36();
            fe = new FileEntity();
            fe.setId(fileId);
            fe.setName(mpFile.getName());
            fe.setSize(mpFile.getSize());
            fe.setStoredContent(fe.getId()+"-"+fe.getName());
            fe.setContentTye(mpFile.getContentType());
            String docType = contentTypeMap.get(fe.getContentTye());
            InputStream inputStream = null;

            try {
                inputStream = mpFile.getInputStream();

                //word转PDF
                if("doc".equals(docType)||"docx".equals(docType)){
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    WordKit.wordToPdf(inputStream,outputStream);
                    IOKit.close(inputStream);
                    inputStream = new ByteArrayInputStream(outputStream.toByteArray());
                    fe.setContentTye("application/pdf");
                }

                fileManage.saveFile(fe,inputStream);
            } catch (IOException e) {
                throw e;
            } catch (Exception e) {
                throw new RoberException("",e);
            } finally {
                IOKit.close(inputStream);
            }
        }
        return fe;
    }

    @RequestMapping(value = "/upload-file", method = RequestMethod.POST)
    @ResponseBody
    public Map<String,Object> uploadFile(HttpServletRequest request, MultipartHttpServletRequest multiRequest) {
        Map<String,Object> ret = MapKit.newLinkedHashMap();
        // 获取上传文件的路径
        FileEntity fe = null;
        try {
            fe = saveFileAsSingle(multiRequest, imageFileService);
            ret.put("success",1);
            ret.put("message","文件上传成功");
            ret.put("url", WebHolder.getServletContext().getContextPath()+"/article/show-file/"+fe.getId());
        } catch (IOException e) {
            ret.put("success",0);
            ret.put("message","保存上传文件出错");
            logger.error("",e);
            return ret;
        }

        return ret;

    }
    @RequestMapping(value = "/upload-doc", method = RequestMethod.POST)
    @ResponseBody
    public Map<String,Object> uploadDoc(HttpServletRequest request, MultipartHttpServletRequest multiRequest) {
        Map<String,Object> ret = MapKit.newLinkedHashMap();
        // 获取上传文件的路径
        FileEntity fe = null;
        try {
            fe = saveFileAsSingle(multiRequest, docFileService);
            ret.put("success",true);
            ret.put("message","文件上传成功");
            ret.put("url", WebHolder.getServletContext().getContextPath()+"/article/show-file/"+fe.getId());
        } catch (IOException e) {
            ret.put("success",false);
            ret.put("message","保存上传文件出错");
            logger.error("",e);
            return ret;
        }

        return ret;

    }

    @RequestMapping("/show-file/{fileId}")
    public void showFile(@PathVariable("fileId") String fileId, HttpServletResponse response) {
        FileEntity fileEntity = imageFileService.getFileEntity(fileId);
        if(fileEntity == null)return;
        InputStream inputStream = null;
        if(fileEntity.getContentTye().startsWith("image/")){
            try {
                inputStream = imageFileService.openInputStream(fileId);
            } catch (IOException e) {
                throw new RoberException(e);
            }
        }else if(fileEntity.getContentTye().startsWith("application/pdf")){
            try {
                inputStream = docFileService.openInputStream(fileId);
            } catch (IOException e) {
                throw new RoberException(e);
            }
        }
        if(inputStream==null)return;

        String conentType = fileEntity.getContentTye();
        if(StringKit.isBlank(conentType))conentType = "image/"+FileKit.getSuffix(fileEntity.getName());
        Map<String,String> headers = MapKit.newHashMap();
        HttpKit.renderStream(response,inputStream,conentType,headers);

        IOKit.close(inputStream);
    }

    @RequestMapping("/ueditor-process")
    public void ueditorProcess(@RequestParam("action") String action,HttpServletRequest request, HttpServletResponse response) throws IOException {
        String charset = request.getCharacterEncoding();
        if(charset==null)Charset.defaultCharset().toString();

        if("config".equals(action)){        //取配置信息
            URL jsonConfigFile = getClass().getClassLoader().getResource("group/rober/jeki/ueditor-config.json");
            InputStream inputStream = jsonConfigFile.openStream();
            Map<String,String> headers = MapKit.newLinkedHashMap();
            HttpKit.renderStream(response,inputStream,"text/html;charset="+charset,headers);
            IOKit.close(inputStream);
        }else if("uploadimage".equals(action)){ //上传图片
            FileEntity fe = null;
            Map<String,Object> ret = MapKit.newLinkedHashMap();
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
            try {
                fe = saveFileAsSingle(multiRequest, imageFileService);
                ret.put("original",fe.getName());
                ret.put("name",fe.getName());
                ret.put("url",WebHolder.getServletContext().getContextPath()+"/article/show-file/"+fe.getId());
                ret.put("size",""+fe.getSize());
                ret.put("type",FileKit.getSuffix(fe.getName()));
                ret.put("state","SUCCESS");
            } catch (IOException e) {
                ret.put("state","FAIL");
                logger.error("",e);
            }
            String jsonText = JSONKit.toJsonString(ret);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonText.getBytes(Charset.defaultCharset()));
            Map<String,String> headers = MapKit.newLinkedHashMap();
            HttpKit.renderStream(response,inputStream,"text/html;charset="+charset,headers);
            IOKit.close(inputStream);
        }
    }

    private void fillArticleModel(Article article,Map<String,Object> vars){
        vars.put("article",article);
        vars.put("tagNames",StringKit.nvl(article.getTags(),"").split(","));
        vars.put("domainTagsList",domainService.getAllDomainTags());
    }
}
